/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model.dao;

import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import model.pojo.Professor;
import model.pojo.Disciplina;
import model.pojo.Aluno;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;
import model.dao.exceptions.NonexistentEntityException;
import model.pojo.Atividade;
import model.pojo.Falta;
import model.pojo.Turma;

/**
 *
 * @author Filipe
 */
public class TurmaJpaController implements TurmaInterface {

    public TurmaJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;
   
    @Override
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    @Override
    public void create(Turma turma) {
        if (turma.getAluno() == null) {
            turma.setAluno(new ArrayList<Aluno>());
        }
        if (turma.getAtividade() == null) {
            turma.setAtividade(new ArrayList<Atividade>());
        }
        if (turma.getFalta() == null) {
            turma.setFalta(new ArrayList<Falta>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Professor professor = turma.getProfessor();
            if (professor != null) {
                professor = em.getReference(professor.getClass(), professor.getId());
                turma.setProfessor(professor);
            }
            Disciplina disciplina = turma.getDisciplina();
            if (disciplina != null) {
                disciplina = em.getReference(disciplina.getClass(), disciplina.getId());
                turma.setDisciplina(disciplina);
            }
            Collection<Aluno> attachedAluno = new ArrayList<Aluno>();
            for (Aluno alunoAlunoToAttach : turma.getAluno()) {
                alunoAlunoToAttach = em.getReference(alunoAlunoToAttach.getClass(), alunoAlunoToAttach.getId());
                attachedAluno.add(alunoAlunoToAttach);
            }
            turma.setAluno(attachedAluno);
            Collection<Atividade> attachedAtividade = new ArrayList<Atividade>();
            for (Atividade atividadeAtividadeToAttach : turma.getAtividade()) {
                atividadeAtividadeToAttach = em.getReference(atividadeAtividadeToAttach.getClass(), atividadeAtividadeToAttach.getId());
                attachedAtividade.add(atividadeAtividadeToAttach);
            }
            turma.setAtividade(attachedAtividade);
            Collection<Falta> attachedFalta = new ArrayList<Falta>();
            for (Falta faltaFaltaToAttach : turma.getFalta()) {
                faltaFaltaToAttach = em.getReference(faltaFaltaToAttach.getClass(), faltaFaltaToAttach.getId());
                attachedFalta.add(faltaFaltaToAttach);
            }
            turma.setFalta(attachedFalta);
            em.persist(turma);
            if (professor != null) {
                professor.getTurma().add(turma);
                professor = em.merge(professor);
            }
            if (disciplina != null) {
                Turma oldTurmaOfDisciplina = disciplina.getTurma();
                if (oldTurmaOfDisciplina != null) {
                    oldTurmaOfDisciplina.setDisciplina(null);
                    oldTurmaOfDisciplina = em.merge(oldTurmaOfDisciplina);
                }
                disciplina.setTurma(turma);
                disciplina = em.merge(disciplina);
            }
            for (Aluno alunoAluno : turma.getAluno()) {
                alunoAluno.getTurma().add(turma);
                alunoAluno = em.merge(alunoAluno);
            }
            for (Atividade atividadeAtividade : turma.getAtividade()) {
                Turma oldTurmaOfAtividadeAtividade = atividadeAtividade.getTurma();
                atividadeAtividade.setTurma(turma);
                atividadeAtividade = em.merge(atividadeAtividade);
                if (oldTurmaOfAtividadeAtividade != null) {
                    oldTurmaOfAtividadeAtividade.getAtividade().remove(atividadeAtividade);
                    oldTurmaOfAtividadeAtividade = em.merge(oldTurmaOfAtividadeAtividade);
                }
            }
            for (Falta faltaFalta : turma.getFalta()) {
                Turma oldTurmaOfFaltaFalta = faltaFalta.getTurma();
                faltaFalta.setTurma(turma);
                faltaFalta = em.merge(faltaFalta);
                if (oldTurmaOfFaltaFalta != null) {
                    oldTurmaOfFaltaFalta.getFalta().remove(faltaFalta);
                    oldTurmaOfFaltaFalta = em.merge(oldTurmaOfFaltaFalta);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public void edit(Turma turma) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Turma persistentTurma = em.find(Turma.class, turma.getId());
            Professor professorOld = persistentTurma.getProfessor();
            Professor professorNew = turma.getProfessor();
            Disciplina disciplinaOld = persistentTurma.getDisciplina();
            Disciplina disciplinaNew = turma.getDisciplina();
            Collection<Aluno> alunoOld = persistentTurma.getAluno();
            Collection<Aluno> alunoNew = turma.getAluno();
            Collection<Atividade> atividadeOld = persistentTurma.getAtividade();
            Collection<Atividade> atividadeNew = turma.getAtividade();
            Collection<Falta> faltaOld = persistentTurma.getFalta();
            Collection<Falta> faltaNew = turma.getFalta();
            if (professorNew != null) {
                professorNew = em.getReference(professorNew.getClass(), professorNew.getId());
                turma.setProfessor(professorNew);
            }
            if (disciplinaNew != null) {
                disciplinaNew = em.getReference(disciplinaNew.getClass(), disciplinaNew.getId());
                turma.setDisciplina(disciplinaNew);
            }
            Collection<Aluno> attachedAlunoNew = new ArrayList<Aluno>();
            for (Aluno alunoNewAlunoToAttach : alunoNew) {
                alunoNewAlunoToAttach = em.getReference(alunoNewAlunoToAttach.getClass(), alunoNewAlunoToAttach.getId());
                attachedAlunoNew.add(alunoNewAlunoToAttach);
            }
            alunoNew = attachedAlunoNew;
            turma.setAluno(alunoNew);
            Collection<Atividade> attachedAtividadeNew = new ArrayList<Atividade>();
            for (Atividade atividadeNewAtividadeToAttach : atividadeNew) {
                atividadeNewAtividadeToAttach = em.getReference(atividadeNewAtividadeToAttach.getClass(), atividadeNewAtividadeToAttach.getId());
                attachedAtividadeNew.add(atividadeNewAtividadeToAttach);
            }
            atividadeNew = attachedAtividadeNew;
            turma.setAtividade(atividadeNew);
            Collection<Falta> attachedFaltaNew = new ArrayList<Falta>();
            for (Falta faltaNewFaltaToAttach : faltaNew) {
                faltaNewFaltaToAttach = em.getReference(faltaNewFaltaToAttach.getClass(), faltaNewFaltaToAttach.getId());
                attachedFaltaNew.add(faltaNewFaltaToAttach);
            }
            faltaNew = attachedFaltaNew;
            turma.setFalta(faltaNew);
            turma = em.merge(turma);
            if (professorOld != null && !professorOld.equals(professorNew)) {
                professorOld.getTurma().remove(turma);
                professorOld = em.merge(professorOld);
            }
            if (professorNew != null && !professorNew.equals(professorOld)) {
                professorNew.getTurma().add(turma);
                professorNew = em.merge(professorNew);
            }
            if (disciplinaOld != null && !disciplinaOld.equals(disciplinaNew)) {
                disciplinaOld.setTurma(null);
                disciplinaOld = em.merge(disciplinaOld);
            }
            if (disciplinaNew != null && !disciplinaNew.equals(disciplinaOld)) {
                Turma oldTurmaOfDisciplina = disciplinaNew.getTurma();
                if (oldTurmaOfDisciplina != null) {
                    oldTurmaOfDisciplina.setDisciplina(null);
                    oldTurmaOfDisciplina = em.merge(oldTurmaOfDisciplina);
                }
                disciplinaNew.setTurma(turma);
                disciplinaNew = em.merge(disciplinaNew);
            }
            for (Aluno alunoOldAluno : alunoOld) {
                if (!alunoNew.contains(alunoOldAluno)) {
                    alunoOldAluno.getTurma().remove(turma);
                    alunoOldAluno = em.merge(alunoOldAluno);
                }
            }
            for (Aluno alunoNewAluno : alunoNew) {
                if (!alunoOld.contains(alunoNewAluno)) {
                    alunoNewAluno.getTurma().add(turma);
                    alunoNewAluno = em.merge(alunoNewAluno);
                }
            }
            for (Atividade atividadeOldAtividade : atividadeOld) {
                if (!atividadeNew.contains(atividadeOldAtividade)) {
                    atividadeOldAtividade.setTurma(null);
                    atividadeOldAtividade = em.merge(atividadeOldAtividade);
                }
            }
            for (Atividade atividadeNewAtividade : atividadeNew) {
                if (!atividadeOld.contains(atividadeNewAtividade)) {
                    Turma oldTurmaOfAtividadeNewAtividade = atividadeNewAtividade.getTurma();
                    atividadeNewAtividade.setTurma(turma);
                    atividadeNewAtividade = em.merge(atividadeNewAtividade);
                    if (oldTurmaOfAtividadeNewAtividade != null && !oldTurmaOfAtividadeNewAtividade.equals(turma)) {
                        oldTurmaOfAtividadeNewAtividade.getAtividade().remove(atividadeNewAtividade);
                        oldTurmaOfAtividadeNewAtividade = em.merge(oldTurmaOfAtividadeNewAtividade);
                    }
                }
            }
            for (Falta faltaOldFalta : faltaOld) {
                if (!faltaNew.contains(faltaOldFalta)) {
                    faltaOldFalta.setTurma(null);
                    faltaOldFalta = em.merge(faltaOldFalta);
                }
            }
            for (Falta faltaNewFalta : faltaNew) {
                if (!faltaOld.contains(faltaNewFalta)) {
                    Turma oldTurmaOfFaltaNewFalta = faltaNewFalta.getTurma();
                    faltaNewFalta.setTurma(turma);
                    faltaNewFalta = em.merge(faltaNewFalta);
                    if (oldTurmaOfFaltaNewFalta != null && !oldTurmaOfFaltaNewFalta.equals(turma)) {
                        oldTurmaOfFaltaNewFalta.getFalta().remove(faltaNewFalta);
                        oldTurmaOfFaltaNewFalta = em.merge(oldTurmaOfFaltaNewFalta);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = turma.getId();
                if (findTurma(id) == null) {
                    throw new NonexistentEntityException("The turma with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Turma turma;
            try {
                turma = em.getReference(Turma.class, id);
                turma.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The turma with id " + id + " no longer exists.", enfe);
            }
            Professor professor = turma.getProfessor();
            if (professor != null) {
                professor.getTurma().remove(turma);
                professor = em.merge(professor);
            }
            Disciplina disciplina = turma.getDisciplina();
            if (disciplina != null) {
                disciplina.setTurma(null);
                disciplina = em.merge(disciplina);
            }
            Collection<Aluno> aluno = turma.getAluno();
            for (Aluno alunoAluno : aluno) {
                alunoAluno.getTurma().remove(turma);
                alunoAluno = em.merge(alunoAluno);
            }
            Collection<Atividade> atividade = turma.getAtividade();
            for (Atividade atividadeAtividade : atividade) {
                atividadeAtividade.setTurma(null);
                atividadeAtividade = em.merge(atividadeAtividade);
            }
            Collection<Falta> falta = turma.getFalta();
            for (Falta faltaFalta : falta) {
                faltaFalta.setTurma(null);
                faltaFalta = em.merge(faltaFalta);
            }
            em.remove(turma);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public List<Turma> findTurmaEntities() {
        return findTurmaEntities(true, -1, -1);
    }

    @Override
    public List<Turma> findTurmaEntities(int maxResults, int firstResult) {
        return findTurmaEntities(false, maxResults, firstResult);
    }

    private List<Turma> findTurmaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Turma as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    @Override
    public Turma findTurma(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Turma.class, id);
        } finally {
            em.close();
        }
    }

    @Override
    public int getTurmaCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Turma as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
